#ifndef DetectorConstruction_h
#define DetectorConstruction_h

#include <geant4/globals.hh>
#include <geant4/G4ThreeVector.hh>
#include <geant4/G4VUserDetectorConstruction.hh>
#include "CathodeSD.hh"


class G4Box;
class G4Tubs;
class G4Cons;
class G4Ellipsoid;
class G4SubtractionSolid;
class G4UnionSolid;
class G4BooleanSolid;
class G4LogicalVolume;
class G4VPhysicalVolume;
class G4Material;
class G4VPVParameterisation;
class G4UserLimits;
class Messenger;
class G4OpticalSurface;

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

class DetectorConstruction : public G4VUserDetectorConstruction
{
  public:
  
     DetectorConstruction();
    ~DetectorConstruction();

  public:
  
     G4VPhysicalVolume* Construct();

     void setScintillationMaterial(G4String);
     void setScintillatorFaceSurface(G4String);
     void setScintillatorLateralSurface(G4String);
     void setScintillatorShape(G4String);
     void setSourceDistance(G4double);
     void setScintDiameter(G4double);
     void setScintHeadDiameter(G4double);
     void setScintThickness(G4double);
     void setPMTDiameter(G4double);
     void setWindowThickness(G4double);
     void setEnvelopeThickness(G4double);
     void setGreaseThickness(G4double);
     void setShellThickness(G4double);
     void setAirGap(G4double);
     void setDefaultDimensions();
     void updateDetector();
     void setFileName(G4String fn);
     void setSaveOption(CathodeSD::SaveData type, bool save);

     G4String getFileName() const;
     void Print(std::ostream &stream = G4cout); // prints detector information

  private:

     G4Box*             solidWorld;    // pointer to the solid envelope 
     G4LogicalVolume*   logicWorld;    // pointer to the logical envelope
     G4VPhysicalVolume* physiWorld;    // pointer to the physical envelope
     
     G4Cons*            solidConicalScint;   // pointer to the conic solid Scintillator
     G4Ellipsoid*       solidEllipsoidalScint; // pointer to the ellipsoidal solid Scintillator
     G4LogicalVolume*   logicScint;   // pointer to the logical Scintillator
     G4VPhysicalVolume* physiScint;   // pointer to the physical Scintillator
               
     G4Cons*             solidConicalShellShaft;  // pointer to the conic solid Shell
     G4Cons*             solidConicalShellCap;  // pointer to the solid Cap
     G4Ellipsoid*        solidEllipsoidalShellBase; // base shape
     G4Ellipsoid*        solidEllipsoidalShellInterior; // subtracted interior
     G4BooleanSolid*     solidShell; // pointer to the ellipsoidal solid Shell
     G4LogicalVolume*    logicShell;  // pointer to the logical Shell
     G4VPhysicalVolume*  physiShell;  // pointer to the physical Shell
     G4Cons*             solidAirCap;  // pointer to the solid Air between Scint and Cap
     G4LogicalVolume*    logicAirCap;  // pointer to the logical Air between Scint and Cap
     G4VPhysicalVolume*  physiAirCap;  // pointer to the physical Air between Scint and Cap

     G4Tubs*            solidGrease;
     G4LogicalVolume*   logicGrease;
     G4VPhysicalVolume* physiGrease;

     G4Tubs*            solidWindow;
     G4Tubs*            solidShaft;
     G4UnionSolid*      solidEnvelope;
     G4LogicalVolume*   logicEnvelope;
     G4VPhysicalVolume* physiEnvelope;


     G4Tubs*            solidCathode;  // pointer to the solid Cathode
     G4LogicalVolume*   logicCathode;  // pointer to the logical Cathode
     G4VPhysicalVolume* physiCathode;  // pointer to the physical Cathode

     Messenger* messenger;  // pointer to the Messenger

     G4String sScintillationMaterial;
     G4String sScintillatorFaceSurface;
     G4String sScintillatorLateralSurface;
     G4String sScintillatorShape;

     // surfaces
     G4OpticalSurface *BGOPolishedAirTeflon; // polished BGO surface wrapped with teflon
     G4OpticalSurface *BGOGroundAirTeflon;   // ground BGO surface wrapped with teflon
     G4OpticalSurface *polishedAir;          // polished crystal surface, not wrapped
     G4OpticalSurface *groundAir;            // ground crystal surface, not wrapped
     G4OpticalSurface *polishedWhitePainted; // polished crystal surface painted white
     G4OpticalSurface *groundWhitePainted;   // ground crystal surface painted white
     G4OpticalSurface *polishedBlackPainted; // polished crystal surface painted black
     G4OpticalSurface *groundBlackPainted;   // ground crystal surface painted black

     G4OpticalSurface *airGroundAluminum; // ground aluminm surface
     G4OpticalSurface *silicaCathodeMaterial; // surface between window and cathode

     // arbitraryly valued variables (not changeable by user)
     G4double fWorldLength;            // Full length of the world volume
     G4double fPMTLength;
     G4double fCathodeThickness;

     // user-changeable variables
     G4double fSourceDistance;
     G4double fScintBaseDiameter;          // The scintillator's base diameter
     G4double fScintHeadDiameter;          // The scintillator's head diameter
     G4double fScintThickness;         // The scintillator's thickness
     G4double fPMTDiameter;
     G4double fWindowThickness;
     G4double fEnvelopeThickness;
     G4double fGreaseThickness;
     G4double fShellThickness;
     G4double fAirGap; // Size of the gap between scintillator and cap/shell

     CathodeSD* theCathodeSD;

     void update();
     void defineMaterials();
     void defineSurfaces();
     G4VPhysicalVolume* constructDetector();

     G4String filename;

     G4OpticalSurface* getSurfaceObjectByName(G4String name) const;
     void updateWorldLength();
};

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

#endif
